package dao

import (
	"context"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"time"
)

type InterActiveDAO interface {
	IncrReadCnt(ctx context.Context, biz string, bizId int64) error
	IncrLike(ctx context.Context, biz string, articleId int64, userId int64) error
	DecrLike(ctx context.Context, biz string, articleId int64, userId int64) error
}

type GORMInterActiveDAO struct {
	db *gorm.DB
}

func NewGORMInterActiveDAO(db *gorm.DB) InterActiveDAO {
	return &GORMInterActiveDAO{
		db: db,
	}
}

func (dao *GORMInterActiveDAO) DecrLike(ctx context.Context, biz string, articleId int64, userId int64) error {
	// 开启事务
	return dao.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		// 1. 取消点赞记录
		now := time.Now().UnixMilli()
		err := tx.WithContext(ctx).Model(&UserLikeBiz{}).
			Where("biz=? and biz_id=? and user_id=?", biz, articleId, userId).
			Updates(map[string]any{
				"utime":  now,
				"status": 2,
			}).Error
		if err != nil {
			return err
		}
		// 2. 维持点赞数量
		return tx.WithContext(ctx).
			Model(&UserLikeBiz{}).
			Where("biz=? and biz_id=?", biz, articleId).
			Updates(map[string]any{
				"like_cnt": gorm.Expr("like_cnt - 1"),
				"utime":    now,
			}).Error
	})
}

func (dao *GORMInterActiveDAO) IncrLike(ctx context.Context, biz string, articleId int64, userId int64) error {
	// 开启事务
	return dao.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		// 能不能调换顺序？？？ 不能否则会存在重复刷赞问题
		// 1. 新增点赞记录
		now := time.Now().UnixMilli()
		var userLikeBiz = UserLikeBiz{
			Biz:    biz,
			BizId:  articleId,
			Status: 1,
			UserId: userId,
			Ctime:  now,
			Utime:  now,
		}
		err := tx.WithContext(ctx).Clauses(clause.OnConflict{
			DoUpdates: clause.Assignments(map[string]any{
				"status": 1,
				"utime":  now,
			}),
		}).Create(&userLikeBiz).Error
		if err != nil {
			return err
		}
		// 2. 维持点赞数量
		var interactive = Interactive{
			Biz:        biz,
			BizId:      articleId,
			ReadCnt:    0,
			LikeCnt:    1,
			CollectCnt: 0,
			Ctime:      now,
			Utime:      now,
		}
		return tx.WithContext(ctx).Clauses(clause.OnConflict{
			DoUpdates: clause.Assignments(map[string]any{
				"like_cnt": gorm.Expr("like_cnt + 1"),
				"utime":    now,
			}),
		}).Create(&interactive).Error
	})
}

func (dao *GORMInterActiveDAO) IncrReadCnt(ctx context.Context, biz string, bizId int64) error {
	now := time.Now().UnixMilli()
	var interactive = Interactive{
		Biz:        biz,
		BizId:      bizId,
		ReadCnt:    1,
		CollectCnt: 0,
		LikeCnt:    0,
		Ctime:      now,
		Utime:      now,
	}
	return dao.db.WithContext(ctx).Clauses(clause.OnConflict{
		DoUpdates: clause.Assignments(map[string]any{
			"read_cnt": gorm.Expr("read_cnt + 1"),
			"utime":    now,
		}),
	}).Create(&interactive).Error
}

// Interactive 交互表
type Interactive struct {
	Id         int64  `gorm:"primaryKey,autoIncrement"`                    // 主键
	Biz        string `gorm:"uniqueIndex:idx_biz_bizid;type:varchar(128)"` // 业务标识
	BizId      int64  `gorm:"uniqueIndex:idx_biz_bizid"`                   // 业务标识id
	ReadCnt    int64  // 阅读数
	LikeCnt    int64  // 点赞数
	CollectCnt int64  // 收藏数
	Ctime      int64  // 创建时间
	Utime      int64  // 更新时间
}

// UserLikeBiz 用户点赞
type UserLikeBiz struct {
	Id     int64  `gorm:"primaryKey,autoIncrement"`
	Biz    string `gorm:"uniqueIndex:idx_biz_bizId_userId;type:varchar(128)"`
	BizId  int64  `gorm:"uniqueIndex:idx_biz_bizId_userId"`
	UserId int64  `gorm:"uniqueIndex:idx_biz_bizId_userId"`
	Status int
	Ctime  int64
	Utime  int64
}
